package v1

import (
	"fmt"
	"log"
	"net/http"
	"toy-car/models"
	"toy-car/pkg/e"
	"toy-car/pkg/util"

	"github.com/astaxie/beego/validation"
	"github.com/gin-gonic/gin"
	"github.com/unknwon/com"
)

type Register struct {
	Username    string `json:"userName" valid:"Required; MaxSize(50)"`
	Password    string `json:"password" valid:"Required; MaxSize(50)"`
	Nickname    string `json:"nickName" valid:"MaxSize(50)"`
	Avatar      string `json:"avatar"`
	Authorities []uint `json:"authorities"`
}

type PasswordChanged struct {
	Username    string `json:"userName" valid:"Required; MaxSize(50)"`    // 用户名
	Password    string `json:"password" valid:"Required; MaxSize(50)"`    // 密码
	NewPassword string `json:"newPassword" valid:"Required; MaxSize(50)"` // 新密码
}

type AuthorityID struct {
	AID string `json:"aid" valid:"Required"`
}

// 获取当前登录用户基本信息，包括权限
func UserCurrent(c *gin.Context) {
	var current interface{}
	var claims *util.Claims
	var ok bool
	if current, ok = c.Get("claims"); !ok {
		e.Fail(e.ERROR_AUTH, nil, "", c)
		return
	}

	log.Printf("%v", current)

	if claims, ok = current.(*util.Claims); !ok {
		e.Fail(e.ERROR_AUTH, nil, "", c)
		return
	}

	log.Printf("--> %v", current)
	user, err := models.GetSysUserByLoginName(claims.Username)
	if err != nil {
		e.Fail(e.ERROR_AUTH, nil, "", c)
		return
	}

	// todo 获取用户菜单和权限项
	log.Printf("--> %v <-- ", current)
	// var menus []models.SysMenu
	// if claims.UserType > 0 {
	// 	menus, err = models.GetAllMenuList()
	// } else {
	// 	menus, err = models.GetMenuListByUserId()
	// }
	// log.Printf("--> %v <-- ", menus)
	e.Success(user, "", c)
}

func UserInfo(c *gin.Context) {
	id := com.StrTo(c.Param("id")).MustInt64()
	user, err := models.GetSysUserByUserId(id)
	if err != nil {
		e.Fail(e.ERROR_AUTH, nil, "", c)
		return
	}

	e.Success(user, "", c)
}
func UserRegister(c *gin.Context) {
	var registerData Register

	_ = c.ShouldBindJSON(&registerData)

	// post参数检验
	valid := validation.Validation{}
	ok, _ := valid.Valid(&registerData)
	data := make(map[string]interface{})
	code := e.SUCCESS
	if !ok {
		code = e.INVALID_PARAMS
		c.JSON(http.StatusOK, gin.H{
			"code": code,
			"msg":  e.GetMSG(code),
			"data": registerData,
		})
		return
	}

	var authorities []models.SysAuthority
	for _, v := range registerData.Authorities {
		authorities = append(authorities, models.SysAuthority{
			AuthorityId: v,
		})
	}

	// 入库
	user := models.SysUser{
		Username:    registerData.Username,
		Password:    registerData.Password,
		Name:        registerData.Nickname,
		HeaderImg:   registerData.Avatar,
		AuthorityId: registerData.Authorities[0],
		Authorities: authorities,
	}
	err, userRet := models.RegistAuth(user)
	if err != nil {
		code = e.INVALID_PARAMS
		c.JSON(http.StatusOK, gin.H{
			"code": code,
			"msg":  err.Error(),
			"data": data,
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": userRet,
	})
}

func UserChangePassword(c *gin.Context) {
	var passwordData PasswordChanged

	_ = c.ShouldBindJSON(&passwordData)
	// post参数检验
	valid := validation.Validation{}
	ok, _ := valid.Valid(&passwordData)
	data := make(map[string]interface{})
	code := e.SUCCESS
	if !ok {
		code = e.INVALID_PARAMS
	} else {
		user := &models.SysUser{
			Username: passwordData.Username,
			Password: passwordData.Password,
		}
		err, _ := models.ChangePassword(user, passwordData.NewPassword)
		if err != nil {
			code = e.ERROR_AUTH
		}
	}
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": data,
	})
}

func UserResetPassword(c *gin.Context) {
	id := com.StrTo(c.Param("id")).MustInt()

	code := e.SUCCESS

	user := &models.SysUser{
		ID: uint(id),
	}

	// todo 比对删除自己，返回错误
	err, _ := models.ResetPassword(user)
	if err != nil {
		code = e.ERROR
	}

	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": true,
	})
}

func UserListWithPage(c *gin.Context) {
	page, pageSize := util.GetPageAndSize(c)
	var userList models.SysUser
	err := c.ShouldBindQuery(&userList)
	var where = make(map[string]interface{})
	if userList.Username != "" {
		where["userName"] = userList.Username
	}

	if userList.Name != "" {
		where["name"] = userList.Name
	}

	log.Printf("userList -->> %v", userList)
	data := make(map[string]interface{})
	code := e.SUCCESS
	err, list, total := models.GetPagedUsers(page, pageSize, where)
	if err != nil {
		code = e.ERROR
	}
	data["page"] = page
	data["pageSize"] = pageSize
	data["data"] = list
	data["total"] = total
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": data,
	})
}

func UserDelete(c *gin.Context) {
	id := com.StrTo(c.Param("id")).MustInt()

	data := make(map[string]interface{})
	code := e.SUCCESS

	// todo 比对删除自己，返回错误
	err := models.DeleteUser(id)
	if err != nil {
		code = e.ERROR
	}

	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": data,
	})
}

func UserAuthorityChanged(c *gin.Context) {
	uid := com.StrTo(c.Param("id")).MustInt()
	var aid AuthorityID
	_ = c.ShouldBindJSON(&aid)
	fmt.Println(uid)
	fmt.Println(aid)
	// 本人无法修改本人的权限
	err := models.ChangeAuthority(uid, aid.AID)
	data := make(map[string]interface{})
	code := e.SUCCESS
	if err != nil {
		code = e.ERROR
	}

	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": data,
	})
}

func UserUpdate(c *gin.Context) {
	uid := com.StrTo(c.Param("id")).MustInt()
	var info models.SysUser
	_ = c.ShouldBindJSON(&info)

	if len(info.AuthorityIds) != 0 {
		err := models.SetUserAuthorities(uint(uid), info.AuthorityIds)
		if err != nil {
			c.JSON(http.StatusOK, gin.H{
				"code": 500,
				"msg":  e.GetMSG(500),
				"data": err.Error(),
			})
			return
		}
	}

	log.Println("err", info.AuthorityIds)
	newInfo := models.SysUser{
		ID:          uint(uid),
		Username:    info.Username,
		Name:        info.Name,
		HeaderImg:   info.HeaderImg,
		AuthorityId: info.AuthorityIds[0],
		Enable:      info.Enable,
	}

	err, _ := models.UpdateUser(newInfo, uid)
	data := make(map[string]interface{})
	code := e.SUCCESS
	if err != nil {
		code = e.ERROR
	}

	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": data,
	})
}
